﻿#region Copyright & licence

// This file is part of Refix.
// 
// Refix is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
// 
// Refix is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with Refix.  If not, see <http://www.gnu.org/licenses/>.
// 
// Copyright (C) 2010-11 David Musgrove and others.

#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using Refix.Core.Properties;

namespace Refix.Core.Structure
{
    public class ConsoleVisualizationStructureVisitor : IPositionAwareStructureVisitor
    {
        private Stack<string> _prefixes;

        public bool IsPlain { get; set; }

        #region IPositionAwareStructureVisitor Members

        public bool ProjectParent { get; set; }

        public void ProcessSolution(Solution solution)
        {
            using (OutputWriter.Highlight(ConsoleColor.White, !IsPlain))
            {
                OutputWriter.WriteLine(ResourceDispenser.GetString("VISUALIZE_SOLUTION"),
                    Path.GetFileName(solution.FileName));
            }
        }

        public void ProcessProject(Project project)
        {
            bool last = NextPosition == Position.Last;
            string prefix = IsPlain
                                ? (last ? "\\--" : "+--")
                                : (last ? "└──" : "├──");
            string continuation = IsPlain
                                      ? (last ? "   " : "|  ")
                                      : (last ? "   " : "│  ");
            OutputWriter.Write(string.Join("", _prefixes.Reverse().ToArray()) + prefix);
            using (OutputWriter.Highlight(ConsoleColor.White, !IsPlain))
            {
                WriteProjectName(project);
            }
            _prefixes.Push(continuation);
        }

        public void ProcessBinaryReference(BinaryReference binaryReference)
        {
            bool last = NextPosition == Position.Last;
            string prefix = IsPlain
                                ? (last ? "\\--" : "+--")
                                : (last ? "└──" : "├──");
            string continuation = IsPlain
                                      ? (last ? "   " : "|  ")
                                      : (last ? "   " : "│  ");
            OutputWriter.Write(string.Join("", _prefixes.Reverse().ToArray()) + prefix);
            WriteBinaryReferenceName(binaryReference);
            _prefixes.Push(continuation);
        }

        public void AfterProcessSolution()
        {
            OutputWriter.WriteLine();
            if (OutputWriter.Verbository == OutputVerbosity.Verbose)
            {
                WriteKey();
            }
        }

        protected virtual void WriteKey()
        {
        }

        public void AfterProcessProject()
        {
            _prefixes.Pop();
        }

        public void AfterProcessBinaryReference()
        {
            _prefixes.Pop();
        }

        public void Visit(Solution solution)
        {
            _prefixes = new Stack<string>();
            solution.AcceptVisitor(this);
        }

        public virtual void Visit(Project project)
        {
            project.AcceptVisitor(this);
        }

        public virtual void Visit(BinaryReference binaryReference)
        {
            binaryReference.AcceptVisitor(this);
        }

        public Position NextPosition { get; set; }

        #endregion

        protected virtual void WriteProjectName(Project project)
        {
            OutputWriter.WriteLine(Path.GetFileName(project.Name));
        }

        protected virtual void WriteBinaryReferenceName(BinaryReference binaryReference)
        {
            OutputWriter.WriteLine("{0} ({1})", binaryReference.Name, binaryReference.OriginalVersion);
        }
    }
}